import type { Ref } from 'vue'
import { onMounted, onUnmounted, nextTick } from 'vue'

interface UseDragOptions {
  fullscreen: Ref<boolean> // 全屏状态响应式引用
  modalRef: Ref<HTMLElement> // 模态框元素的响应式引用
}

/**
 * 模态框拖拽功能的自定义 Hook
 * 实现标题栏拖拽移动模态框的功能，并处理全屏状态限制
 */
export const useDrag = (options: UseDragOptions) => {
  const initPosition = ref({ left: 0, top: 0 }) // 初始位置

  /**
   * 注册标题栏拖拽事件
   * @param dragEl - 被拖拽元素（模态框）
   * @param handleEl - 拖拽手柄（标题栏）
   */
  const registerDrag = (dragEl: HTMLElement, handleEl: HTMLElement) => {
    // 设置标题栏光标为移动样式
    handleEl.style.cursor = 'move'

    // 鼠标按下事件（节流处理，20ms 间隔）
    const handleMouseDown = (e: MouseEvent) => {
      // 若为全屏状态，则不允许拖拽
      if (options.fullscreen.value) return
      document.body.style.userSelect = 'none'

      // 鼠标起始位置（相对于页面）
      const startX = e.clientX
      const startY = e.clientY

      // 获取屏幕宽高（用于边界限制）
      const screenWidth = document.body.clientWidth
      const screenHeight = document.documentElement.clientHeight

      // 获取模态框的尺寸
      const modalWidth = dragEl.offsetWidth
      const modalHeight = dragEl.offsetHeight

      // 计算模态框当前在页面中的偏移位置（用于计算拖动边界）
      const minLeft = dragEl.offsetLeft // 左侧最小可拖动距离（不能拖出左边）
      const maxLeft = screenWidth - minLeft - modalWidth // 右侧最大可拖动距离
      const minTop = dragEl.offsetTop // 顶部最小可拖动距离
      const maxTop = screenHeight - minTop - modalHeight // 底部最大可拖动距离

      // 获取模态框的初始定位属性
      const computedStyle = getComputedStyle(dragEl)
      let startLeft = parseFloat(computedStyle.left)
      let startTop = parseFloat(computedStyle.top)

      // 如果是百分比布局，需要将百分比转为像素值
      if (computedStyle.left.includes('%')) {
        startLeft = (document.body.clientWidth * parseFloat(computedStyle.left)) / 100
        startTop = (document.body.clientHeight * parseFloat(computedStyle.top)) / 100
      }

      /**
       * 拖动中的处理函数（鼠标移动时调用）
       */
      const handleMouseMove = (moveEvent: MouseEvent) => {
        if (options.fullscreen.value) return

        // 计算鼠标拖动的偏移距离
        let deltaX = moveEvent.clientX - startX
        let deltaY = moveEvent.clientY - startY

        // 限制横向拖动范围
        deltaX = Math.min(Math.max(-minLeft, deltaX), maxLeft)
        // 限制纵向拖动范围
        deltaY = Math.min(Math.max(-minTop, deltaY), maxTop)

        // 计算新的 left/top 值
        const newLeft = startLeft + deltaX
        const newTop = startTop + deltaY

        // 设置新的位置（仅限 top/left 定位的模态框）
        dragEl.style.left = `${newLeft}px`
        dragEl.style.top = `${newTop}px`
      }

      /**
       * 拖动结束时移除事件绑定，释放资源
       */
      const handleMouseUp = () => {
        document.removeEventListener('mousemove', handleMouseMove!)
        document.removeEventListener('mouseup', handleMouseUp!)
        document.body.style.userSelect = 'auto' // 恢复文本可选中
      }

      // 绑定全局事件，用于监听拖动
      document.addEventListener('mousemove', handleMouseMove)
      document.addEventListener('mouseup', handleMouseUp)
    }

    // 绑定鼠标按下事件
    handleEl.removeEventListener('mousedown', handleMouseDown)
    handleEl.addEventListener('mousedown', handleMouseDown)
  }

  /**
   * 初始化拖拽功能
   */
  const initDrag = async () => {
    await nextTick()
    const modalEl = options.modalRef.value?.querySelector('.ant-modal') as HTMLElement
    const headerEl = modalEl?.querySelector('.ant-modal-header') as HTMLElement
    if (modalEl && headerEl) {
      // 注册标题栏拖拽事件
      registerDrag(modalEl, headerEl)
      // 记录初始化位置
      const computedStyle = getComputedStyle(modalEl)
      initPosition.value.left = parseFloat(computedStyle.left)
      initPosition.value.top = parseFloat(computedStyle.top)
    }
  }

  /**
   * 重置模态框位置到初始状态
   */
  const resetPosition = () => {
    const modalEl = options.modalRef.value?.querySelector('.ant-modal') as HTMLElement
    if (modalEl) {
      modalEl.style.left = `${initPosition.value.left}px`
      modalEl.style.top = `${initPosition.value.top}px`
    }
  }

  // 组件挂载时初始化
  onMounted(() => {
    initDrag()
  })

  // 组件卸载时清理事件
  onUnmounted(() => {})

  return {
    initDrag, // 暴露初始化方法，可手动触发
    resetPosition
  }
}
